/**
 *******************************************************************************
 * @FileName  : user_main.c
 * @Author    : GaoQiu
 * @CreateDate: 2020-05-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */
#include "user_main.h"
#include "utils/mdc.h"
#include "user_main.h"
#include "utils/pool_buf.h"
#include "utils/msg.h"
#include "utils/stimer.h"
#include "utils/math.h"
#include "utils/heap.h"
#include "utils/lg_mem.h"

#include "stack/hci_transport/hci_tr_api.h"
#include "stack/controller/ll_api.h"
#include "stack/controller/bb_api.h"
#include "stack/hci_defs.h"
#include "stack/controller/lhci_api.h"
#include "stack/ant/ant_api.h"

#include "bsp/bsp.h"

#include "component/kv/kv_api.h"

/*!< Heap Size */
#define APP_HEAP_MEM_SIZE  (8 * 1024)
static uint32_t heap[APP_HEAP_MEM_SIZE/sizeof(uint32_t)] = {0};

/*! LED blink period Unit:ms */
#define APP_LED_EN          1
#define APP_LED_BLINK_PERIOD    1000 //Unit:ms

/*! Enable White-list  */
#define APP_WL_EN           0

/*! Connection parameter configuration */
#define APP_MAX_MST_NUM     1
#define APP_MAX_SLV_NUM     1
#define APP_MAX_CONN_NUM    (APP_MAX_MST_NUM + APP_MAX_SLV_NUM)

/*!< Sleep Clock Source Selected */
#define APP_SLP_CLK_SRC     CFG_SLEEP_CLOCK_SOURCE
#define APP_SCA_PPM         (APP_SLP_CLK_SRC ? 50:800)

/* ACL Size Setting. */
#ifdef IP_108
#define APP_ACL_SIZE            27
#define APP_LL_ENC_TIME_US      300
#elif defined(IP_107)
#define APP_ACL_SIZE            27
#define APP_LL_ENC_TIME_US      100
#endif


/*! HCI config. */
const LhciConfig_t lhciCfg = {
	.maxAclLen  = APP_ACL_SIZE, /*!< max acl parameter length.  >= LL max ACL data length. */
	.maxCmdLen  = 65,  /*!< max cmd parameter length.   */
	.maxEvtLen  = 65,  /*!< max evt parameter length.   */

	.numCmdBufs = 8,   /*!< max rx cmd buffer number.    */
	.numAclBufs = 8,   /*!< max rx acl buffer number.    */
	.numEvtBufs = 8,  /*!< max tx evt/acl buffer number.*/
};

/*! Link layer config. */
const LlCfg_t llCfg = {
	.versNr    = LL_VER_BT_CORE_SPEC,   /*!< BLE Core version.           */
	.compId    = LL_COMPANY_ID,         /*!< Company ID.                 */
	.subVersNr = LL_SUB_VERSION_NUM,    /*!< Implementation version.     */

	.wlNum     = 4,                     /*!< White-list size.            */
	.rlNum     = 0,                     /*!< Resolve list size.          */

	/* Extended adv / scan */
	.numAdvSet         = 0,
	.extAdvDataLen     = 0,
	.extScanRspDataLen = 0,
	.advMargin         = 0,             /*!< unit:ms */

	.maxMst    = APP_MAX_MST_NUM,       /*!< Max number of master connection. */
	.maxSlv    = APP_MAX_SLV_NUM,       /*!< Max number of SLAVE connection. */
	.maxAclLen = APP_ACL_SIZE,          /*!< Length of ACL data.         */
	.numRxBufs = 16,                    /*!< Number of Rx buffer. !!!must be 2^n */
	.numTxBufs = 16,                    /*!< Number of Tx buffer. !!!must be 2^n */
	.localSCA  = APP_SCA_PPM,           /*!< Local sleep clock accuracy. */

	.mstMargin = 6,                     /*!< Master connection margin. Unit: 0.625ms */
	.numMoreDat= 6,                     /*!< the max number of more data. Range: 1-6. */

	.sleepClockSrc = APP_SLP_CLK_SRC,   /*!< [Panchip] select sleep clock source. 0:32k RC, 1:32k XTL. */
	.bbSetupTime = 200,                 /*!< [Panchip] BB PHY setup time. Unit:us */
	.llEncTime   = APP_LL_ENC_TIME_US,  /*!< [Panchip] BB CCM time. Unit:us */

	.authPyldTimeoutEn = false,
	.numMaxAnt = 2,
};

/*! Application main control block. */
typedef struct{
	MdcTimer_t      timer;
	MdcTimer_t      termTimer;
	MdcHandlerId_t  handlerId;
}AppCb_t;

static AppCb_t appCb;

void APP_MsgHandler(MdcEventMask_t event, MdcMsgHdr_t *pMsg)
{
	if(pMsg)
	{
		switch(pMsg->event)
		{
		case APP_EVT_LED_BLINK:
			BSP_LedToggle(LED_PIN_BLUE);
			MDC_TimerStartMs(&appCb.timer, APP_LED_BLINK_PERIOD);
			break;

		case APP_EVT_DISCONN:
			break;

		default:
			break;
		}
	}

	if(event)
	{
	}
}

void Setup(void)
{
	/* BSP initialization. */
	BSP_InitAllLed();

	/* memory initialization. */
	lg_mem_init();
	HeapInit((uint8_t *)&heap[0], APP_HEAP_MEM_SIZE);

	/* kv database initialization. */
	kv_init();

	/* Buffer pool allocate. */
	pool_desc_t pools[] ={
		{16,     8 },
		{32,     4 },
		{80,     8 },
		{280,    2 },
	};
	PoolBufInit(pools, COUNTOF(pools));

	/* MDC system initialization. */
	MDC_Init();

	/* MDC Timer initialization. */
	MDC_TimerInit();

	/* Set MAC address. */
	uint8_t bdAddr[6] = {0x66, 0x66, 0x66, 0x66, 0x00, 0xC4};
	//GetConfigParam(CFG_PARAM_MAC_ADDR, bdAddr, 6);
	LL_SetBdAddr(bdAddr, BD_ADDR_LEN);

	/* LL initialization. */
	LL_Init(&llCfg);
	LL_MstInit();
	LL_SlvInit();
	BB_SetTxPower(CFG_TX_POWER_LVL);

#if ANT_EN
	ANT_Init();
#endif

	/* HCI Configuration */
	LHCI_Init(&lhciCfg);

	/* HCI Transport Init. */
	HCI_TR_Init();

	/* Application initialization. */
	appCb.handlerId = MDC_AddMsgHandler(APP_MsgHandler);
#if APP_LED_EN
	MDC_TimerConfigEx(&appCb.timer, appCb.handlerId, APP_EVT_LED_BLINK, 0, 0);
	MDC_TimerStartMs(&appCb.timer, APP_LED_BLINK_PERIOD);
#endif

#if APP_WL_EN
	/* Set White-list */
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr0);
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr1);
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr2);
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr3);
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr4);
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr5);
	LL_LE_AddDeviceToWhiteList(LL_ADDR_PUBLIC, addr6);
#endif

#if 1
	/* ADV initialization. */
	LL_LE_SetAdvParam(ADV_INTR_30_MS,        /*!< min adv interval.   */
			          ADV_INTR_35_MS,        /*!< max adv interval.   */
			          0,                     /*!< adv event type.     */
			          LL_ADDR_PUBLIC,        /*!< local address type. */
			          LL_ADDR_PUBLIC,        /*!< peer address type.  */
			          NULL,                  /*!< peer address.       */
			          LL_ADV_CHAN_ALL,       /*!< adv channel map.    */
			          LL_ADV_FILTER_NONE);   /*!< adv filter policy.  */

	uint8_t advData[] = {
		0x02, 0x01, 0x06,             /*!< Flag type.  */
		0x05, 0x08, 'P','H','I','D',  /*!< short name. */
		0x03, 0x19, 0x80, 0x01,       /*!< 384, Generic Remote Control, Generic category */
		0x03, 0x02, 0x12, 0x18,       /*!< service UUID */
	};
	uint8_t scanRsp[] = {
		0x05, 0x09, 'P','H','O','D',  /*!< complete name. */
	};
	LL_LE_SetAdvData(advData, sizeof(advData));
	LL_LE_SetScanRspData(scanRsp, sizeof(scanRsp));
	LL_LE_SetAdvEnable(ENABLE);
#endif

#if 0
    /* Scan initialization. */
	LL_LE_SetScanParam(LL_ACTIVE_SCAN,          /*!< scan type.          */
			           SCAN_INTR_50_MS,         /*!< scan interval.      */
			           SCAN_INTR_50_MS,         /*!< scan window.        */
			           LL_ADDR_PUBLIC,          /*!< local address type. */
			           LL_SCAN_FILTER_NONE);    /*!< scan filter policy. */
	LL_LE_SetScanEnable(ENABLE, DISABLE);
#endif

#if 0
	/* ANT Test */
	uint32_t tick = GetCurSysTick();
	ab_event_node_t antAdv;
	antAdv.interval      = BB_US_TO_TICK(25000);
	antAdv.slot_duration = 2;
	antAdv.before_point  = 0;
	antAdv.anchor_point  = tick;
	antAdv.AntStartCback = App_AntStartCback;
	antAdv.AntStopCback  = NULL;
	antAdv.priority      = 0;

	ANT_Create(&antAdv);

	antAdv.anchor_point  = tick + BB_US_TO_TICK(2000);
	ANT_Create(&antAdv);
//
//	antAdv.anchor_point  = tick + BB_US_TO_TICK(6000);
//	ANT_Create(&antAdv);
//
//	antAdv.anchor_point  = tick + BB_US_TO_TICK(12000);
//	ANT_Create(&antAdv);
#endif

#if 0 //DTM
	BB_DtmStartTransimitterV2(0, 37, 0x00, 1);
#endif
}

uint32_t A_Loop = 0;
void Loop(void)
{
	A_Loop++;

	/* HCI Transport task */
	HCI_TR_TaskStart();

	/* BLE Stack task */
	MDC_Start();
}

